package com.feinno.urcs.group.siptask;

import com.feinno.sip.address.SipUri;
import com.feinno.sip.header.ContentType;
import com.feinno.sip.header.ContributionID;
import com.feinno.sip.header.ConversationID;
import com.feinno.sip.header.extensions.ReferredBy;
import com.feinno.sip.message.SipRequest;
import com.feinno.sip.util.IDUtils;
import com.feinno.threading.Future;
import com.feinno.threading.FutureListener;
import com.feinno.urcs.content.MimeType;
import com.feinno.urcs.content.UrcsMultipartMimeContent;
import com.feinno.urcs.group.GroupConfiguration;
import com.feinno.urcs.group.api.GroupService;
import com.feinno.urcs.group.entity.GroupIndex;
import com.feinno.urcs.group.entity.GroupInfo;
import com.feinno.urcs.group.siptask.task.GroupMessageArgs;
import com.feinno.urcs.group.siptask.task.GroupTaskEvents;
import com.feinno.urcs.nai.IMPU;
import com.feinno.urcs.sip.SipConnector;
import com.feinno.urcs.sip.UrcsSipFactory;
import com.feinno.urcs.sipservlet.SipConnectorLoader;
import com.feinno.urcs.sipservlet.uac.RcsPageModeUAC;
import com.feinno.urcs.sipservlet.uac.RcsSipUACArgs;
import com.feinno.urcs.sipservlet.uac.RcsUACFactory;
import com.feinno.urcs.sipservlet.uac.RcsUACVisitorAdapter;
import com.feinno.util.Result;
import org.helium.framework.annotations.FieldSetter;
import org.helium.framework.annotations.ServiceSetter;
import org.helium.framework.annotations.TaskImplementation;
import org.helium.framework.task.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.ParseException;

/**
 * Created by wuhao on 5/11/15.
 */
@TaskImplementation(event = GroupTaskEvents.GROUP_PAGE_MODE_MESSAGE)
public class GroupPagerMessageTask implements Task<GroupMessageArgs> {
    private static final Logger LOGGER = LoggerFactory.getLogger(GroupPagerMessageTask.class);
    @FieldSetter("${CSCF_ADDRESS}")
    private String cscfAddress;
    @FieldSetter(loader = SipConnectorLoader.class, value = "${SIP_STACK_AS}")
    private SipConnector connector;
    @ServiceSetter
    private GroupService groupService;


    /**
     * send message process
     */
    @Override
    public void processTask(GroupMessageArgs args) {
        LOGGER.info("GroupPagerMessageTask Process Start To Mobile:{}", args.getToMobile());
        if (args != null){
            //TODO 处理消息只有Pageode不考虑长度
            LOGGER.debug("send message length = {}", args.getContent().length);
            sendPageMode(args);
        }else{
            LOGGER.debug("nothing to send");
        }
        LOGGER.info("GroupPagerMessageTask Process End");
    }
    /**
     * send page mode
     *
     * */
    public void  sendPageMode(GroupMessageArgs groupMessageArgs){
        LOGGER.info("send pagemode message method start");

        ConversationID conversationID = getConversationID(groupMessageArgs);

        //构造Uac参数
        IMPU sender = getSender(groupMessageArgs);
        IMPU recever = getRecever(groupMessageArgs);
        IMPU grouper = getGrouper(groupMessageArgs);
        RcsSipUACArgs args = new RcsSipUACArgs(grouper, recever);

        //contentType
        ContentType contentType = getContentType(groupMessageArgs);

        //Uac arg cscf
	    SipUri cscf = getCscf(groupMessageArgs);

	    RcsPageModeUAC uac = RcsUACFactory.createPageModeUAC(connector, cscf, args);
        final UrcsMultipartMimeContent content =
                UrcsMultipartMimeContent.newInstance(contentType, groupMessageArgs.getContent());

        //group request refer-by(群消息中的发送者参照)
        ReferredBy referredBy = new ReferredBy();
        referredBy.setAddress(UrcsSipFactory.getAddressFactory().createAddress(
                sender.toUri()
        ));
        //从新构造sip request
        final ConversationID finalConversationID = conversationID;
        uac.accept(new RcsUACVisitorAdapter() {
		    @Override
		    public void visitorSend(SipRequest request) {
                super.visitorSend(request);
                //发送者参照
                if(referredBy != null){
                    request.setHeader(referredBy);
                }
                //群消息唯一ID
                if(finalConversationID != null){
                    request.setHeader(finalConversationID);
                }
                //随机ID
                ContributionID contributionID = new ContributionID(IDUtils.createId(8));
                if(contributionID != null){
                    request.setHeader(contributionID);
                }

		    }
	    });
        //准备发送uac
        Future<Integer> future = uac.begin();
        future.addListener(new FutureListener<Integer>() {
            @Override
            public void run(Result<Integer> result) {
                try {
                    if (result.getValue() != 200) {
                        LOGGER.error("send pagemode message begin callback return {}.", result.getValue());
                        uac.end();
                        return;
                    }
                    Future<Integer> sendFuture = uac.send(content);
                    sendFuture.addListener(new FutureListener<Integer>() {
                        @Override
                        public void run(Result<Integer> result) {
                            if (result.getValue() != 200) {
                                LOGGER.error("send pagemode message send return {}.", result.getValue());
                                uac.end();
                                return;
                            }
                            if (LOGGER.isInfoEnabled()) {
                                LOGGER.info("send pagemode message send successfully: {}", new String(content.toByteArray()));
                            }
                            uac.end();
                        }
                    });
                } catch (Exception e) {
                    LOGGER.error("send pagemode message begin callback return error{}。", e);
                }
            }
        });
        LOGGER.info("send pagemode message method end");
    }

    /**
     * getConversationID
     *
     * @param groupMessageArgs
     * @return
     */
    public ConversationID getConversationID(GroupMessageArgs groupMessageArgs){
        ConversationID conversationID = null;
        try {
            GroupIndex groupIndex = groupService.getGroupIndex(groupMessageArgs.getGroupId());
            GroupInfo  groupInfo = groupService.getGroupInfo(groupIndex);
            conversationID =  new ConversationID(groupInfo.getConversationId());
        } catch (Exception e) {
            LOGGER.error("getConversationId error {}", e);
        }
        return conversationID;
    }

    /**
     * getSender
     *
     * @param groupMessageArgs
     * @return
     */
    public IMPU getSender(GroupMessageArgs groupMessageArgs){
        IMPU sender = null;
        StringBuilder senderSb = new StringBuilder();
        senderSb.append("sip:");
        senderSb.append(groupMessageArgs.getFromMobile());
        senderSb.append("@");
        senderSb.append(GroupConfiguration.INSTANCE.getDomain());
        sender = IMPU.parse(senderSb.toString());
        return  sender;
    }

    /**
     * getGrouper
     *
     * @param groupMessageArgs
     * @return
     */
    public  IMPU getGrouper(GroupMessageArgs groupMessageArgs){
        IMPU group = null;
        group = IMPU.parse(GroupIndex.toConferenceUri(groupMessageArgs.getGroupId()));
        return  group;
    }

    /**
     * getRecever
     *
     * @param groupMessageArgs
     * @return
     */
    public  IMPU getRecever(GroupMessageArgs groupMessageArgs){
        IMPU receiver = null;
        StringBuilder receiverSb = new StringBuilder();
        receiverSb.append("sip:");
        receiverSb.append(groupMessageArgs.getToMobile());
        receiverSb.append("@");
        receiverSb.append(GroupConfiguration.INSTANCE.getDomain());
        receiver = IMPU.parse(receiverSb.toString());
        return  receiver;
    }

    /**
     * getContentType
     *
     * @param groupMessageArgs
     * @return
     */
    public  ContentType getContentType(GroupMessageArgs groupMessageArgs){
        ContentType  contentType = (ContentType) (MimeType.CPIM.getContentTypeHeader());
        return contentType;
    }
    public SipUri getCscf(GroupMessageArgs groupMessageArgs){
        SipUri cscf = null;
        try {
            cscf = (SipUri) UrcsSipFactory.getAddressFactory().createURI(cscfAddress);
        } catch (ParseException e) {
            LOGGER.error("getAddressFactory().createURI(toAddress){}", e);
            throw new RuntimeException(e);
        }
        return cscf;
    }
}